%{
#include <stdio.h>
#define YYDEBUG 1
%}

%union{
   int value; 
   char *ident;
}

%token IDENT
%token NUMBER
%token ASSIGNOP
%token DEFINE
%token IF
%token THEN
%token ELSE
%token FI
%token WHILE
%token DO
%token OD
%token PROC
%token END

%%


program: 
	stmt_list 
	{printf("program -> stmt_list\n"); }
;

stmt_list:  
	stmt ';' stmt_list 
	{ printf("stmt_list -> stmt ; stmt_list\n"); }
	|
	stmt  
	{ printf("stmt_list -> stmt\n"); }
;

stmt:  
	assign_stmt 
	{ printf("stmt -> assign_stmt\n"); }
	|  
	define_stmt 
	{ printf("stmt -> define_stmt\n"); }
	|  
	if_stmt 
	{ printf("stmt -> if_stmt\n"); }
	|
	while_stmt 
	{ printf("stmt -> while_stmt\n"); }
;

mixed:
	expr
	{ printf("mixed -> expr \n"); }
	|
	proc	
	{ printf("mixed -> proc \n"); }
;

assign_stmt: 
	IDENT ASSIGNOP mixed 
	{ printf("assign_stmt -> identifier := mixed \n"); }
;

bracketed_param_list: 
	'(' param_list ')' 
	{ printf("bracketed_param_list -> ( param_list ) \n"); }
	| 
	'(' ')' 
	{ printf("bracketed_param_list -> ( ) \n"); }
;
	   
define_stmt: 
	DEFINE IDENT proc
	{ printf("define_stmt -> define identifier proc \n"); }
;

if_stmt: 
	IF expr THEN stmt_list ELSE stmt_list FI
	{ printf("if_stmt -> IF expr THEN stmt_list ELSE stmt_list FI\n"); }
;

while_stmt: 
	WHILE expr DO stmt_list OD
	{ printf("while_stmt -> WHILE expr DO stmt_list OD\n"); }
;

param_list: 
	IDENT ',' param_list 
	{ printf("param_list -> IDENT, param_list\n"); }
	|
	IDENT 
	{ printf("param_list -> IDENT\n"); }
;
	
expr:
	expr '+' term
	{ printf("expr -> expr + term\n"); }
	|
	expr '-' term
	{ printf("expr -> expr - term\n"); }
	|
	term
	{ printf("expr -> term\n"); }
;

term:
	term '*' factor
	{ printf("term -> term * factor\n"); }
	|
	factor
	{ printf("term -> factor\n"); }
;

factor:
	'(' expr ')'
	{ printf("factor -> ( expr ) \n"); }
	|
	NUMBER 
	{ printf("factor -> number\n"); }
	|
	IDENT 
	{ printf("factor -> identifier \n"); }
	|
	funcall 
	{ printf("factor -> funcall\n"); }
;

operator: 
	'+'
	{ printf("operator -> + \n"); }
	|
	'-'
	{ printf("operator -> - \n"); }
	|
	'*'
	{ printf("operator -> * \n"); }
;
	
argument: 
	'(' ')'
	{ printf("argument -> ( ) \n"); }
	|
	'(' mixed_list ')'
	{ printf("argument -> ( mixed_list ) \n"); }
;
	
funcall:
	proc argument 
	{printf("funcall -> proc argument \n");}
	|
	funcall argument
	{printf("funcall -> funcall argument \n");} 
	|
	IDENT argument
	{ printf("funcall -> identifier argument\n"); }
;
	
mixed_list: 
	mixed ',' mixed_list
	{ printf("mixed_list -> mixed , mixed_list\n"); }
	|
	mixed 
	{ printf("mixed_list -> mixed \n"); }
;
		
proc: 
	PROC bracketed_param_list stmt_list END
	{ printf("proc -> proc bracketed_param_list stmt_list end \n"); }
	|
	operator
	{ printf("proc -> operator\n"); }
;	

%%

main(int argc, char **argv)
{
	yyparse();
}

yyerror(char *errmsg)
{
	fprintf(stderr, "%s\n", errmsg);
}
